import { Selection, BaseType } from 'd3-selection';
import L, { LatLng } from 'leaflet';

import { FeatureInstance, FeatureOption } from '../types';
import Feature from './feature';
import { deepClone } from '../util/util';

class Point extends Feature {
    constructor(id: string, featureOption: FeatureOption, loc: LatLng, style: any, properties?: any) {
        super(id, featureOption, [[loc]], 'point', properties);
    }

    add(groupSelection: Selection<SVGGElement | BaseType, Feature, BaseType, string>) {
        groupSelection
            .selectChildren('path.point')
            .data(['shadow', 'stroke'])
            .enter()
            .append('path')
            .call(this.pointPath.bind(this));

        this.group = groupSelection;
        this.addEventListener();
        this.redraw();

        return this;
    }

    redraw() {
        const latLng = this.latLngs[0][0];
        if (!latLng) {
            this.featureOption.remove(this.type, this.id);
            return this;
        }
        this.group!.attr('transform', () => this.featureOption.transform.translate(latLng));
        return this;
    }

    pointPath(selection: Selection<SVGPathElement, string, BaseType, unknown>) {
        selection
            .attr('class', (klass) => {
                return this.type + ' ' + klass;
            })
            .attr('transform', 'translate(-8, -23)')
            .attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
    }

    remove(): void {
        this.group.remove();
        this.latLngs = [];
    }
    changeLatlng(latLng: L.LatLng, indexs: number[], sequenceNum = 0): void {
        this.latLngs[sequenceNum].splice(indexs[0], 1, latLng);
        this.redraw();
    }

    toPoint(): L.Point {
        const pix = this.featureOption.transform.project(this.latLngs[0][0]);
        return L.point(pix[0], pix[1]);
    }

    instance() {
        const attr: FeatureInstance = {
            ...this.json(),
            getInstanceType: this.getInstanceType.bind(this),
            changeId: this.changeId.bind(this),
            setProperties: this.setProperties.bind(this),
            isEmpty: this.isEmpty.bind(this),
        };
        return deepClone(attr);
    }
}

export default Point;
